package com.aptech.springaop83.proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 模拟性能监控
 * 
 * 该方法会被需要增加监控的所有方法调用，具有典型的业务横切特性
 * 
 * 备注： 该方法使用ThreadLocal，来解决并发的问题；
 * ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本
 * ，通过访问副本来运行业务，这样的结果是耗费了内存，单大大减少了线程同步所带来性能消耗，也减少了线程并发控制的复杂度。
 * ThreadLocal不能使用原子类型，只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。
 * 
 * ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。
 * synchronized是利用锁的机制
 * ，使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本，使得每个线程在某一时间访问到的并不是同一个对象
 * ，这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反，它用于在多个线程间通信时能够获得数据共享。
 * 
 * Synchronized用于线程间的数据共享，而ThreadLocal则用于线程间的数据隔离。
 * 
 * @author Ryan
 * 
 */
public class PerformanceMonitor {

	private static final Logger logger = LoggerFactory.getLogger(PerformanceMonitor.class);
	
	private static ThreadLocal<MethodPerformace> performaceRecord = new ThreadLocal<MethodPerformace>();

	/**
	 * 开始监控
	 * 
	 * @param method
	 *            监控的方法名称
	 */
	public static void begin(String method) {
		
		logger.info("begin monitor...");
		
		// 从当前线程中获取方法监控对象
		MethodPerformace mp = performaceRecord.get();
		
		if (mp == null) {
			
			mp = new MethodPerformace(method);
			
			performaceRecord.set(mp);
			
		} else {
			
			mp.reset(method);
		}
	}

	/**
	 * 结束监控
	 */
	public static void end() {
		
		logger.info("end monitor...");
		
		MethodPerformace mp = performaceRecord.get();
		
		mp.printPerformace();
	}
}
